/**
 * 图上标绘
 * @copyright 火星科技 mars3d.cn
 * @author 火星胡椒 && 火星渣渣灰  2022-02-19
 */
import * as mars3d from "mars3d"
import * as api from "@mars/common/api"
import { $message } from "@mars/components/mars-ui/index"
import * as kgUtil from "kml-geojson"
import { saveGeoJSON2Kml, readJSON } from "@mars/utils/file-util"
import { logInfo, logWarn } from "@mars/utils/mars-util"

export const eventTarget = new mars3d.BaseClass()

let map: mars3d.Map // 地图对象
let graphicLayer: mars3d.layer.GraphicLayer

// 初始化当前业务
export function onMounted(mapInstance: mars3d.Map): void {
  map = mapInstance // 记录map

  graphicLayer = new mars3d.layer.GraphicLayer({
    name: "图上标绘",
    pid: 99, // 图层管理 中使用，父节点id
    isRestorePositions: false, // 在标绘和编辑结束时，是否将坐标还原为普通值，true: 停止编辑时会有闪烁，但效率要好些。
    isAutoEditing: true
  })
  map.addLayer(graphicLayer)

  const editUpdateFun = mars3d.Util.funDebounce(graphicLayer_editUpdate, 500)
  graphicLayer.on(
    [
      mars3d.EventType.drawCreated,
      mars3d.EventType.editStart,
      mars3d.EventType.editMovePoint,
      mars3d.EventType.editStyle,
      mars3d.EventType.editRemovePoint
    ],
    editUpdateFun
  )
  const removeFun = mars3d.Util.funDebounce(graphicLayer_remove, 500)
  graphicLayer.on(mars3d.EventType.removeGraphic, removeFun)

  graphicLayer.bindContextMenu([
    {
      text: "删除对象",
      icon: "fa fa-trash-o",
      callback: function (e: any) {
        e.graphic.remove(true)
      }
    }
  ])

  // 加载历史数据
  getHistoricalRecordsList()
}

// 释放当前业务
export function onUnmounted(): void {
  if (historyId) {
    updateHistoryRecords()
  } else {
    historyId = addHistoricalRecords()
  }

  if (graphicLayer) {
    graphicLayer.destroy() // 销毁内部会释放所有事件及数据
    graphicLayer = null
  }

  eventTarget.off()
  map = null
}

// ******************** 事件 ********************
// 修改样式，修改点，删除点等操作去激活或更新面板
function graphicLayer_editUpdate(e) {
  logInfo("标绘进行了修改操作", e)
  eventTarget.fire("plot_graphicEditor", { graphicId: e.graphic.id, layerId: graphicLayer.id })
}

function graphicLayer_remove(e) {
  logInfo("标绘触发删除操作", e)
  eventTarget.fire("plot_graphicEditor", { disable: true })
}

// 保存文件
export function onClickMarkerSavefile() {
  if (graphicLayer.length === 0) {
    $message("当前没有标注任何数据，无需保存！")
    return
  }
  const json = graphicLayer.toJSON()
  mars3d.Util.downloadFile("我的标绘数据.json", JSON.stringify(json))
}

// 打开保存的文件
export async function impFile(file: any, isClearLayer: boolean) {
  const fileName = file.name
  const fileType = fileName?.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase()

  if (fileType === "json" || fileType === "geojson") {
    const jsonData = await readJSON(file)
    graphicLayer.loadJSON(jsonData, {
      flyTo: true,
      clear: isClearLayer
    })
  } else if (fileType === "kml") {
    const reader = new FileReader()
    reader.readAsText(file, "UTF-8")
    reader.onloadend = function (e) {
      const strkml = this.result
      kgUtil.toGeoJSON(strkml).then((geojson) => {
        console.log("kml2geojson", geojson)

        graphicLayer.loadGeoJSON(geojson, { flyTo: true })
      })
    }
  } else if (fileType === "kmz") {
    // 加载input文件控件的二进制流
    kgUtil.toGeoJSON(file).then((geojson) => {
      console.log("kmz2geojson", geojson)

      graphicLayer.loadGeoJSON(geojson, { flyTo: true })
    })
  } else {
    $message("暂不支持 " + fileType + " 文件类型的数据！")
  }
}

// 清空
export function onClickMarkerDeleteAll() {
  graphicLayer.clear()
  historyId = null
  deleteHistoricalRecordsById()
}

// 是否可以编辑
export function onClickMarkerEditor(val: boolean) {
  graphicLayer.isAutoEditing = val
}

// 是否开启Popup
export function isShowPopup(val: boolean) {
  if (val) {
    graphicLayer.bindPopup((event: any) => {
      const graphic = event.graphic.parent || event.graphic
      const html = mars3d.Util.getTemplateHtml({
        title: "属性编辑",
        template: [
          { field: "my_name", name: "业务名称" },
          { field: "my_remark", name: "业务备注", type: "textarea" },
          { name: "确定", type: "button", className: "mars3d-popup-btn-custom" }
        ],
        attr: graphic.attr,
        edit: true,
        width: 190
      })
      return html
    })

    graphicLayer.on(mars3d.EventType.popupOpen, (event: any) => {
      const container = event.container
      // 打开popup之后的确定按钮
      const btnOk = container.querySelector(".mars3d-popup-btn")

      if (btnOk) {
        const graphic = event.graphic.parent || event.graphic
        btnOk.addEventListener("click", () => {
          const popupEdititem: any = document.querySelectorAll(".mars3d-popup-edititem")
          popupEdititem.forEach((item) => {
            let key = item.getAttribute("data-type")

            if (!key) {
              key = ""
            }
            graphic.attr[key] = item.value
          })
          // 同步修改编辑面板的属性
          eventTarget.fire("plot_graphicEditor", { graphicId: graphic.id, layerId: graphicLayer.id, isOpen: false })
          map.closePopup()
        })
      }
    })
  } else {
    graphicLayer.unbindPopup()
    graphicLayer.off(mars3d.EventType.popupOpen)
  }
}

// 加载数据
function loadJSON(json: any, options: any) {
  graphicLayer.loadJSON(json, options)
}

// *****************************************标号面板*********************************** //
// 开始标记
export async function startDraw(drawOptions: any) {
  drawOptions = mars3d.Util.clone(drawOptions) // 需要拷贝

  if (drawOptions.positions) {
    delete drawOptions.positions
  }
  if (drawOptions.position) {
    delete drawOptions.position
  }

  await graphicLayer.startDraw({
    drawShow: true, // 绘制时，是否显示模型，可避免在3dtiles上拾取坐标存在问题。
    ...drawOptions
  })
}

export function updateTemplateValues(url: any) {
  if (map?.templateValues) {
    return mars3d.Util.template(url, map.templateValues)
  } else {
    return url
  }
}

// ******************************************列表面板********************************** //
export function getGraphicsTree(params) {
  if (!graphicLayer) {
    return null
  }

  return graphicLayer.getGraphicsTree(params)
}

// 添加新的分组|修改分组名称
export function addNewPlotTree(groupId: string, treeName: string, isAddNew: boolean) {
  if (isAddNew) {
    // 新增
    const graphic = new mars3d.graphic.GroupGraphic({ name: treeName })
    graphicLayer.addGraphic(graphic)

    eventTarget.fire("refreshTree", {
      key: "add",
      node: {
        key: graphic.id,
        id: graphic.id,
        name: treeName,
        open: false,
        group: true,
        type: "group",
        children: []
      }
    })
  } else {
    const graphic = graphicLayer.getGraphicById(groupId)

    if (graphic) {
      // 修改
      graphic.name = treeName
      eventTarget.fire("refreshTree", { key: "change", nodeId: groupId, obj: { name: treeName } })
    }
  }
}

// 定位至对应的矢量数据
export function flyToPlotTreeGraphic(id: string) {
  const graphic = graphicLayer.getGraphicById(id)
  map.flyToGraphic(graphic)
}

// 打开编辑面板
export function openEditorPannel(id: string, isFly: boolean = false) {
  const graphic = graphicLayer.getGraphicById(id)
  if (graphic) {
    graphic.show = true
    isFly && graphic.flyTo()
    graphic.startEditing()
  } else {
    logWarn("未找到对应的矢量数据")
  }
}

// 显示隐藏对应矢量数据
export function showHideGarahic(checked: boolean, node: any) {
  refreshGraphicLayer([node], (nodeId) => {
    const graphic = graphicLayer.getGraphicById(nodeId)
    if (graphic) {
      graphic.show = checked
    }
  })
}

// 删除对应矢量数据
export function onMenuDeleted(node: any) {
  refreshGraphicLayer([node], (nodeId) => {
    const graphic = graphicLayer.getGraphicById(nodeId)
    if (graphic) {
      graphic.remove()
      eventTarget.fire("refreshTree", { key: "remove", nodeId })
    }
  })
}

// 拖拽矢量
export function moveToLayer(graphicId: string, pid: string) {
  const graphic = graphicLayer.getGraphicById(graphicId)
  if (graphic) {
    graphic.pid = pid
  }
}

// 下载geoJSON
export function onMenuSaveGeojson(node: any, name: string) {
  const groupItem = graphicLayer.getGraphicById(node.id)
  if (!groupItem) {
    return
  }

  const json = [groupItem.toJSON()]
  if (node.group) {
    if (!node.children?.length) {
      $message("当前没有任何数据，无需保存！")
      return
    }

    refreshGraphicLayer(node.children, (nodeId) => {
      const graphic = graphicLayer.getGraphicById(nodeId)
      json.push(graphic.toJSON())
    })
  }

  logInfo("保存的数据 json", json)

  mars3d.Util.downloadFile(name + ".json", JSON.stringify(json))
}

export function onMenuSaveKML(node: any, name: string) {
  const groupItem = graphicLayer.getGraphicById(node.id)
  if (!groupItem) {
    return
  }

  const json = [groupItem.toGeoJSON()]
  if (node.group) {
    if (!node.children?.length) {
      $message("当前没有任何数据，无需保存！")
      return
    }

    refreshGraphicLayer(node.children, (nodeId) => {
      const graphic = graphicLayer.getGraphicById(nodeId)
      json.push(graphic.toGeoJSON())
    })
  }

  logInfo("保存的数据 geojson", json)

  const kml = saveGeoJSON2Kml(json, { name })
  mars3d.Util.downloadFile(name + ".kml", kml)
}

function refreshGraphicLayer(node, callback) {
  node.forEach((item) => {
    if (item.key) {
      callback(item.key)
    }
    if (item.group && item.children.length) {
      refreshGraphicLayer(item.children, callback)
    }
  })
}

// *************** 与后端接口操作 ***************

let historyId: any
const storageType = "mars3d_plot"

// 获取所有的历史数据
async function getHistoricalRecordsList() {
  // const { code, data } = await api.getHistoricalRecordsList({ type: storageType })
  // if (code === 200 && data) {
  //   const item = data.find((item) => item.type === storageType)
  //   logInfo("获取到历史数据 mars3d_plot", data, item)

  //   if (!item) { return }
  //   historyId = item?.id
  //   if (item?.content) {
  //     loadJSON(JSON.parse(item.content), { clear: true, flyTo: true })
  //   }
  // } else {
  //   loadDemoData()
  // }
}

// 实际系统时可以注释下面代码，该代码是mars3d官网在线加载演示数据
async function loadDemoData() {
  if (window.location.hostname.indexOf("mars") === -1) {
    return
  }
  const result = await mars3d.Util.fetchJson({ url: "//data.mars3d.cn/file/geojson/mars3d-draw.json" })
  if (result) {
    loadJSON(result, { clear: true, flyTo: true })
  }
}

// 添加历史数据
async function addHistoricalRecords() {
  // const json = graphicLayer.toJSON()

  // const { code, data } = await api.addHistoricalRecords({
  //   title: json.name,
  //   type: storageType,
  //   content: JSON.stringify(json)
  // })

  // if (code === 200 && data) {
  //   return data.id
  // }
}

// 更新历史数据
async function updateHistoryRecords() {
  const json = graphicLayer.toJSON()

  // const { code } = await api.updateHistoryRecords({
  //   id: historyId,
  //   title: json.name,
  //   type: storageType,
  //   content: JSON.stringify(json)
  // })

  // if (code === 200) {
  //   logInfo("更新历史数据")
  // } else {
  //   logInfo("更新失败")
  // }
}

// 删除历史数据
async function deleteHistoricalRecordsById() {
  // const { code } = await api.deleteHistoricalRecordsById(historyId)

  // if (code === 200) {
  //   logInfo("删除历史数据")
  // } else {
  //   logInfo("删除失败")
  // }
}
